#include "ParticleSystem.h"

ParticleSystem::ParticleSystem(){
	Reset();
}

void ParticleSystem::Reset(){
	mName = new string("Explosion");
	mExpandRate = 1.0f;// 2.0f* Random();
	mDecayRate = 1.2f;//* Random() + 0.4f;
	mPower = 2.0f;// * Random();
	mSpawnScale = 0.8f;//0.2f* Random() + 0.69f;
	ini = false;
	mNodes= new vector<ExplosionNode*> ();
	mTemp = new vector<ExplosionNode*> ();
	mDone= false;
	mDelay = 300;
	srand(time(0));
	srand(Random());
	mMaxDepth = 15;
	radius = 0.5;
	mLifeTime = 800;
	cosine = 0.9;


	for(int a =0; a < 100; a ++){
		ExplosionNode* mNew = new ExplosionNode();
		mNew->TimeRemaining =0;
		mNew->Pos = new D3DXVECTOR3(0,0,0);
			mNew->Dir = new D3DXVECTOR3(0,0,0);
			mNew->Speed = new D3DXVECTOR3(0,0,0);
			mNew->Color = new D3DXCOLOR(0,0,0,0)	;
		mNodes->push_back(mNew);
	}
}

void ParticleSystem::Reset(float pRadius, float pLifetime, float pCosine, int pGenerator){
	mName = new string("Explosion");
	mExpandRate = 1.0f;// 2.0f* Random();
	mDecayRate = 1.2f;//* Random() + 0.4f;
	mPower = 2.0f;// * Random();
	mSpawnScale = 0.8f;//0.2f* Random() + 0.69f;
	ini = false;
	mNodes= new vector<ExplosionNode*> ();
	mTemp = new vector<ExplosionNode*> ();
	mDone= false;
	mDelay = 300;
	srand(time(0));
	srand(Random());
	mMaxDepth = 15;
	radius = pRadius;
	mLifeTime = pLifetime;
	cosine = pCosine;



	for(int a =0; a < pGenerator; a ++){
		ExplosionNode* mNew = new ExplosionNode();
		mNew->TimeRemaining =0;
		mNew->Pos = new D3DXVECTOR3(0,0,0);
			mNew->Dir = new D3DXVECTOR3(0,0,0);
			mNew->Speed = new D3DXVECTOR3(0,0,0);
			mNew->Color = new D3DXCOLOR(0,0,0,0)	;
		mNodes->push_back(mNew);
	}
}

void ParticleSystem::Update(LPDIRECT3DDEVICE9 d3ddev, double pElapsed, double pTotal){

	D3DXVECTOR3 mDir;
	mDir.x = this->GetPos()->x;
	mDir.y = this->GetPos()->y;
	mDir.z = this->GetPos()->z;

	ModelPrimitive::Update(d3ddev,pElapsed,pTotal);

	mDir.x = mDir.x-this->GetPos()->x;
	mDir.y = mDir.y-this->GetPos()->y;
	mDir.z = mDir.z-this->GetPos()->z;
	::D3DXVec3Normalize(&mDir,&mDir);

	mtime += pElapsed;
	

	for(int a =0; a < mNodes->size(); a++){

		ExplosionNode* cur = mNodes->at(a);

		if(cur->TimeRemaining <=0 &&( mDir.x != 0 || mDir.z != 0 || mDir.y !=0) ){
			D3DXVECTOR3 angle;
			int neg = -1;

			D3DXVECTOR3 rad;

			neg = -1;
			if(Random() >0.5){neg*=neg;}
			rad.x = (1-mDir.x)* radius*Random()*neg;
			
			neg = -1;
			if(Random() >0.5){neg*=neg;}
			rad.y = (1-mDir.y)* radius*Random()*neg;
			
			neg = -1;
			if(Random() >0.5){neg*=neg;}
			rad.z = (1-mDir.z)* radius*Random()*neg;
			
			//::D3DXVec3Normalize(&rad,&rad);

			cur->Pos->x =  GetPos()->x + rad.x *radius ;
			
			cur->Pos->y = GetPos()->y+ rad.y *radius; 

			cur->Pos->z = GetPos()->z+ rad.z *radius;


			float dot=0;
			int count =0;
			neg =-1;
			while(dot < cosine){
				if(Random() >0.5){neg*=neg;}
				angle.x = (1)*Random()*neg;
				
				neg = -1;
				if(Random() >0.5){neg*=neg;}
				angle.y = (1)*Random()*neg;
				
				neg = -1;
				if(Random() >0.5){neg*=neg;}
				angle.z = (1)*Random()*neg;

				/*
				angle.x += rad.x;
				angle.y += rad.y;
				angle.z += rad.z;
				*/

				::D3DXVec3Normalize(&angle,&angle);
				dot = ::D3DXVec3Dot(&mDir,&angle);
				count ++;
			};

			cur->Dir->x = angle.x ;
			cur->Dir->y = angle.y ;
			cur->Dir->z = angle.z ;

			D3DXVECTOR3 speed;

			speed.x = .5;//*Random();
			speed.y = .5;//*Random();
			speed.z = .5;//*Random();

			::D3DXVec3Normalize(&speed,&speed);

			cur->Speed->x = 0.1; //* Random();
			cur->Speed->y = 0.1;// * Random();
			cur->Speed->z = 0.1;// * Random();
			cur->Color->r =0.3f	;
			cur->Color->g =0.3f	;
			cur->Color->b =0.3f	;
			cur->Color->a =1.f	;
			cur->TimeRemaining = mLifeTime*Random();
		}
	
		cur->Pos->x += cur->Dir->x * cur->Speed->x;
		cur->Pos->y += cur->Dir->y * cur->Speed->y;
		cur->Pos->z += cur->Dir->z * cur->Speed->z;
		cur->TimeRemaining -= pElapsed;
		
		cur->Color->r = cur->TimeRemaining/mLifeTime;
		cur->Color->a = cur->TimeRemaining/mLifeTime;
		cur->Color->g = cur->TimeRemaining/mLifeTime;
		cur->Color->b = cur->TimeRemaining/mLifeTime;

	}	
}


D3DXVECTOR3* ParticleSystem::CalcNewNode(D3DXVECTOR3* pos, float power){
	D3DXVECTOR3*mRet = new D3DXVECTOR3();
	float neg;
	mRet->x = Random() * power;
	neg = Random();

	if(neg > 0.5){
		mRet->x = mRet->x * -1.0f;
	}

	mRet->x += pos->x ;

	mRet->y = Random() * power;

		neg = Random();

	if(neg > 0.5){
		mRet->y = mRet->y * -1.0f;
	}
	mRet->y += pos->y ;

	mRet->z = Random() * power;
	
	neg = Random();

	if(neg > 0.5){
		mRet->z = mRet->z * -1.0f;
	}
	mRet->z += pos->z ;

	return mRet;
}

void ParticleSystem::Draw(LPDIRECT3DDEVICE9 d3ddev){
	
	for(int i =0; i < mNodes->size();i++){
		ExplosionNode* mCur = mNodes->at(i);

		mModel->SetPos(mCur->Pos);

		ModelPrimitive* prim = dynamic_cast <ModelPrimitive*> (mModel);
		
		prim->GetMaterial()->Diffuse.g = mCur->Color->g;
		prim->GetMaterial()->Ambient.g = mCur->Color->g;
		prim->GetMaterial()->Specular.g = mCur->Color->g;
		prim->GetMaterial()->Emissive.g =  mCur->Color->g;

		prim->GetMaterial()->Diffuse.r =   mCur->Color->r;
		prim->GetMaterial()->Ambient.r =  mCur->Color->r;
		prim->GetMaterial()->Specular.r =  mCur->Color->r;
		prim->GetMaterial()->Emissive.r = mCur->Color->r;

		prim->GetMaterial()->Diffuse.b =   mCur->Color->b;
		prim->GetMaterial()->Ambient.b =  mCur->Color->b;
		prim->GetMaterial()->Specular.b =  mCur->Color->b;
		prim->GetMaterial()->Emissive.b =  mCur->Color->b;
		
		mModel->Draw(d3ddev);
	}

	ModelPrimitive::Draw(d3ddev);
}
